package com.example.demo2.common.util;

import java.io.UnsupportedEncodingException;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.commons.net.util.Base64;

import com.example.demo2.common.exception.TripleDESException;


/**
 * 类名： TripleDESUtil
 * 
 * <br>
 * 描述：3DES加解密工具类
 * 
 * 
 * @author haplant
 * 
 * @date 2015年4月23日 上午9:27:55
 * 
 * @version 1.0
 * 
 * <br>
 *          Copyright by LANDI.
 * 
 * <br>
 *          Program Name:
 */
public class TripleDESUtil {
	private final transient static Log logger = LogFactory.getLog(TripleDESUtil.class);
	private final static String CHARSET = "UTF-8";
	// 定义加密算法，有DES、DESede、Blowfish
	private final static String ALGORITHM = "DESede";

	/**
	 * 功能描述：加密方法
	 * 
	 * @param src
	 * @param key
	 * @return
	 * @throws TripleDESException
	 * 
	 * @author haplant
	 * 
	 * @date: 2015年4月25日 下午1:33:21
	 */
	private static byte[] encryptMode(final byte[] src, byte[] key) throws TripleDESException {
		byte[] by = null;
		try {
			SecretKey deskey = new SecretKeySpec(key, ALGORITHM); // 生成密钥
			Cipher ci = Cipher.getInstance(ALGORITHM); // 实例化负责加密/解密的Cipher工具类
			ci.init(Cipher.ENCRYPT_MODE, deskey); // 初始化为加密模式
			by = ci.doFinal(src);
		} catch (Exception e) {
			e.printStackTrace();
			logger.error("3DES加密", e);
			throw new TripleDESException("3DES加密过程出错");
		}
		return by;
	}

	/**
	 * 功能描述：解密函数
	 * 
	 * @param src
	 * @param key
	 * @return
	 * @throws TripleDESException
	 * 
	 * @author haplant
	 * 
	 * @date: 2015年4月25日 下午1:33:32
	 */
	private static byte[] decryptMode(byte[] src, byte[] key) throws TripleDESException {
		byte[] by = null;
		try {
			SecretKey deskey = new SecretKeySpec(key, ALGORITHM);
			Cipher ci = Cipher.getInstance(ALGORITHM);
			ci.init(Cipher.DECRYPT_MODE, deskey); // 初始化为解密模式
			by = ci.doFinal(src);
		} catch (Exception e) {
			e.printStackTrace();
			logger.error("3DES解密", e);
			throw new TripleDESException("3DES解密过程出错");
		}
		return by;
	}

	/**
	 * 功能描述：获取3deskey
	 * 
	 * @param keyBase
	 * @return
	 * @throws TripleDESException
	 * 
	 * @author haplant
	 * 
	 * @date: 2015年4月25日 下午1:34:46
	 */
	public static byte[] build3DesKey(String keyBase) throws TripleDESException {
		byte[] key = new byte[24]; // 声明一个24位的字节数组，默认里面都是0
		try {
			byte[] temp = keyBase.getBytes(CHARSET); // 将字符串转成字节数组
			/*
			 * 执行数组拷贝 System.arraycopy(源数组，从源数组哪里开始拷贝，目标数组，拷贝多少位)
			 */
			if (key.length > temp.length) {
				// 如果temp不够24位，则拷贝temp数组整个长度的内容到key数组中
				System.arraycopy(temp, 0, key, 0, temp.length);
			} else {
				// 如果temp大于24位，则拷贝temp数组24个长度的内容到key数组中
				System.arraycopy(temp, 0, key, 0, key.length);
			}
		} catch (Exception e) {
			key = null;
			e.printStackTrace();
			logger.error("3DES获取密钥", e);
			throw new TripleDESException("3DES获取密钥过程出错");
		}
		return key;
	}

	/**
	 * 功能描述：字符串加密
	 * 
	 * @param str
	 * @param key
	 * @return
	 * @throws TripleDESException
	 * 
	 * @author haplant
	 * 
	 * @date: 2015年4月23日 上午10:21:39
	 */
	public static String encrypt(String str, byte[] key) throws TripleDESException {
		String result = "";
		try {
			result = Base64.encodeBase64String(encryptMode(str.getBytes(CHARSET), key));
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
			logger.error("3DES加密转码", e);
			throw new TripleDESException("3DES加密转码过程出错");
		}
		return result;
	}

	/**
	 * 功能描述：字符串解密
	 * 
	 * @param str
	 * @param key
	 * @return
	 * @throws TripleDESException
	 * @throws UnsupportedEncodingException
	 * 
	 * @author haplant
	 * 
	 * @date: 2015年4月23日 上午10:46:43
	 */
	public static String decrypt(String str, byte[] key) throws TripleDESException {
		String result = "";
		try {
			result = new String(decryptMode(Base64.decodeBase64(str), key), CHARSET);
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
			logger.error("3DES解密转码", e);
			throw new TripleDESException("3DES解密转码过程出错");
		}
		return result;
	}
}
